home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
sampler0
/
fastbuff.asm
< prev
next >
Wrap
Assembly Source File
|
1987-11-29
|
32KB
|
939 lines
page 66,132
;
; FASTBUFF.ASM - Keyboard buffer resident utility.
;
; Version 2.0
;
; by: David Steiner
; [D.STEINER] on GEnie
; 2035 J Apt. 6
; Lincoln, NE 68510
; (402) 475-0601
;
; This is a fairly big update from version 1.0. FASTBUFF now
; handles Alt-keypad character entries correctly, plus fixes
; these characters since many IBM clones generate incorrectly.
;
; The way characters are restored to the system has been updated
; also. We no longer hook the Keyboard I/O interrupt, instead we
; continuously keep the BIOS buffer full by filling it every time
; the system timer clicks (Interrupt 1C).
; This was done as an allowance for programs that bypass the BIOS
; when doing character I/O. It has the added benefit of allowing
; FASTBUFF to be active when installed after other utilities that
; hook into interrupt 16.
;
; The only software compatibility problems that should arise will
; be with other programs that hook the Keystroke interrupt and attempt
; to insert characters directly into the BIOS keyboard buffer.
; "Key-fake" utilities are an example of such programs. If you
; need to use such a program, it is best to deactivate FASTBUFF first.
cseg segment
assume cs:cseg, ds:cseg
org 100H
start:
jmp initialize
;
;------ Old vector storage area
;
oldint9 dd
oldint10 dd
oldint1C dd
;------ EQUATES
cr equ 0DH
lf equ 0AH
;------ BIOS buffer & otherstuff equates
BIOSdseg equ 40H ; BIOS data area segment
BIOShead equ 1AH ; BIOS keyboard buffer head
BIOStail equ 1CH ; "" tail
BIOSaltbuff equ 19H ; Storage for Alt-keypad entries
BIOSbuffer equ 1EH ; BIOS keyboard buffer start
BIOSendbuff equ 3EH ; end
BIOSequipflags equ 10H ; BIOS equipment word address
BIOScrtmodeset equ 65H
BIOSpalette equ 66H
equipmask equ 0010H
palettemask equ 0FH
KBinport equ 60H ; Keyboard data port
KBctrlport equ 61H ; Keyboard control port
Altshift equ 38H ; ALT key scan code
;------ BIOS shift status byte 1 & masks for action key combinations
BIOSshflags equ 17H ; First BIOS shift status byte
ClrMask equ 05H ; Clear buffer key mask
altmask equ 08H ; Bit set when Alt is being held down
;------ FASTBUFF control key scan codes
fbctrlkey equ 4CH ; Scan code for "5" on keypad
fbonkey equ 52H ; Code for INS key
fboffkey equ 53H ; Code for DEL key
fbfast equ 4EH ; Code for keypad "+"
fastrep equ 2 ; Chars per click for fast rate
fbslow equ 4AH ; Code for keypad "-"
slowrep equ 1 ; Chars per click for slow rate
;------ BIOS break detection byte
BIOSbreak equ 71H ; Bit 7 of this byte indicates
breakmask equ 80H ; ctrl-break was pressed
;------ Masks for altering bits in our status byte.
fbmask equ 01H ; Masks for FASTBUFF toggle
repmask equ 02H ; On when we need to repeat a character
scrmask equ 04H ; On while screen is active
ctrlmask equ 08H ; On when [5] is being held down
oldint9mask equ 10H ; On when processing char with old int9
vidmask equ 20H ; Video blanking active?
assume ds:nothing
;---------------------------- Int 09 --------------------------------------
;Keystroke Interrupt
;
; Note that we always allow control to pass on to the old interrupt
; 9 handler. We do, however, ignore the characters returned if one
; of FASTBUFF's four command key combinations were detected.
;--------------------------------------------------------------------------
newint9 proc far
sti
push ax
push bx
push cx
push dx
push es
;------ This first section is code always executed by FASTBUFF
and cs:switches,not repmask ; Turn off repeat switch
mov bx,BIOSdseg ; Set ES to BIOS data seg and
mov es,bx ; turn off break bit
and byte ptr es:BIOSbreak,not breakmask
mov cx,cs:screendelay ; Reset screen blank counter
mov cs:scrcount,cx
test cs:switches,scrmask ; Check if video is blanked
jnz skiprestore
call restorescreen ; If so turn it back on
skiprestore:
in al,KBinport ; Get scan code from keyboard
test cs:switches,ctrlmask ; Check if currently in control mode
jz notcontrol
;------ FASTBUFF control key check when keypad #5 is depressed
cmp al,fbctrlkey+80H ; Check if control key was released
jne notreleased
and cs:switches,not ctrlmask ; Turn off control mode
jmp callold9
notreleased:
cmp al,fbonkey
jne k1
or cs:switches,fbmask ; Turn on FASTBUFF
jmp clearall
k1:
cmp al,fboffkey
jne k2
and cs:switches,not fbmask ; Turn off FASTBUFF
jmp clearall
k2:
test byte ptr cs:switches,fbmask ; FASTBUFF on?
jz notpressed
cmp al,fbfast
jne k3
mov cs:repchars,fastrep ; Set fast repeat rate
jmp reset
k3:
cmp al,fbslow
jne notpressed
mov cs:repchars,slowrep ; Set slow repeat rate
jmp reset
clearall:
cli
mov bx,es:BIOStail
mov es:BIOShead,bx ; Clear both keyboard buffers
mov bx,cs:tail
mov cs:head,bx
reset:
cli
mov bx,es:BIOStail ; Allow old interrupt handler to
pushf ; to see the keystroke entered,
call oldint9 ; but ignore any output character.
mov es:BIOStail,bx
sti
jmp int9done
;------ Not currently in control mode so check for other possibilities
notcontrol:
cmp al,fbctrlkey ; Check if our control key pressed
jne notpressed
or cs:switches,ctrlmask ; Turn on control mode
notpressed:
;------ Finally we will check to see if FASTBUFF is active
test byte ptr cs:switches,fbmask ; FASTBUFF on?
jz off1
cmp al,37H ; If Shift-PrtSc is pressed then just
jne on1 ; call old handler and exit
test byte ptr es:BIOSshflags,03H
jz on1
off1:
pushf ; Not on so call old int9 and exit
call oldint9
jmp int9done
on1:
cmp al,altshift+80H ; Check if Alt key released
jne notalt
mov ah,es:BIOSaltbuff ; If so save alt-keypad character
jmp callold9
notalt:
mov bh,es:BIOSshflags
and bh,0FH
cmp bh,clrmask ; Clear key combination pressed?
jne callold9
cli
mov bx,es:BIOStail ; Clear out buffers
mov es:BIOShead,bx
mov bx,cs:tail
mov cs:head,bx
sti
;------ Let the old BIOS handler determine what the ASCII or extended
; character code should be.
callold9:
or cs:switches,oldint9mask ; Set bit so we don't update BIOS buff
mov bx,es:BIOStail ; Make old int 9 do the dirty work
pushf
call oldint9
mov dx,es:[bx] ; Store new char in DX
mov cx,es:BIOStail
mov es:BIOStail,bx
and cs:switches,not oldint9mask
test byte ptr es:BIOSbreak,breakmask
jz checknew
cli
mov es:BIOShead,bx
mov bx,cs:head ; Break detected, clear our buffers
mov word ptr cs:[bx],0 ; and output dummy character
call incbuff
mov cs:tail,bx
sti
jmp int9done
checknew:
cmp bx,cx
jne newchar
mov cs:lastchar,0FFFFH ; Set non-typeable char as lastchar
jmp int9done
newchar:
cmp al,altshift+80H ; Check if Alt key released
jne putin
mov dl,ah ; Fix entered character with keypad
mov dh,0 ; Scan code = 0
putin:
call newinchar
int9done:
pop es
pop dx
pop cx
pop bx
pop ax
iret
newint9 endp
;------ NewInChar - Take char from BIOS buffer and insert it into ours,
; then set repeat switch accordingly.
;
; ES contains BIOSdseg
; DX contains character that was return by old int 9
newinchar proc near
push si
cmp dx,cs:lastchar
je indone ; Ignore character if it was from STD
; repeat function
mov cs:lastchar,dx
mov bh,cs:startdelay ; Set start delay for repeat function
mov cs:repcount,bh
mov bx,cs:tail
mov si,bx ; Save address where char will go
call incbuff
cmp bx,cs:head
jne storchar
call errbeep
jmp indone
storchar:
cli
mov cs:[si],dx ; Store character
mov cs:tail,bx ; Store new tail value
sti
indone:
cmp dh,0 ; Scan code = 0 if entered on keypad
jne switchon
test byte ptr es:BIOSshflags,02H ; Allow chars entered via the
jz reallydone ; keypad to repeat if the user is
switchon: ; holding down the Left Shift key.
or cs:switches,repmask
reallydone:
pop si
ret
newinchar endp
;------ ErrBeep - Keyboard full error beep, from ROM BIOS listing
errbeep proc near
push ax
push bx
push cx
mov bx,030H ; Cycles for 1/16 second tone
in al,61H ; Get keyboard ctrl information
push ax ; Save it
beepcycle:
and al,0FCH ; Turn off timer gate & spkr data
out 61H,al ; Output to control
mov cx,48H ; Half cycle time for tone
l1: loop l1 ; Speaker off
or al,2 ; Turn on speaker bit
out 61H,al ; Output to control
mov cx,48H ; Set up count
l2: loop l2 ; another half cycle
dec bx ; Total time count
jnz beepcycle ; Do another cycle
pop ax ; Recover control
out 61H,al ; Output the control
pop cx ; Recover registers
pop bx
pop ax
ret
errbeep endp
;---------------------------- Int 10 --------------------------------------
;Video I/O
;--------------------------------------------------------------------------
newint10 proc far
sti
cmp ah,0FAH ; Return value to indicate FASTBUFF
jne vid ; is already resident
mov al,ah
xor ah,ah
iret
vid:
push ax
push es
mov ax,cs:screendelay ; Reset screen blanking counter
mov cs:scrcount,ax
test cs:switches,scrmask ; Check if video is currently blanked
jnz skiprest
mov ax,BIOSdseg ; Set up ES reg for RestoreScreen call
mov es,ax
call restorescreen ; If blanked, turn it back on
skiprest:
pop es
pop ax
jmp oldint10 ; Pass control on to normal Video I/O
newint10 endp
;------------------------------- Int 1C -----------------------------------
;Software Timer Tick
;--------------------------------------------------------------------------
newint1C proc far
sti
test cs:switches,fbmask ; FASTBUFF on?
jz timerdone
dec word ptr cs:scrcount ; Check if its time to turn off
jnz dontblank ; the video
test cs:switches,vidmask
jz dontblank
call blankscreen
dontblank:
push ax
push bx
push cx
push dx
push di
push si
push es
mov bx,BIOSdseg
mov es,bx
test byte ptr cs:switches,oldint9mask ; If currently using BIOS buff
jnz skipupdate ; don't try to update it.
call updateBIOS ; Insert characters into BIOS buffer
skipupdate: ; from our buffer.
test cs:switches,repmask
jz norep ; Do nothing if repeat switch
dec cs:repcount ; off or counter not zero yet
jnz norep
call repkey ; Otherwise repeat the key.
norep:
pop es
pop si
pop di
pop dx
pop cx
pop bx
pop ax
timerdone:
jmp oldint1C ; Jump to old timer software int
newint1C endp
;------ UpdateBIOS - Put characters from our buffer into the BIOS buffer
;
; Note: don't fill BIOS buffer completely, leave space for
; at least one character. This is required to allow
; the int9 handler to use this spot as its input buffer.
updateBIOS proc near
mov bx,cs:head ; Pointers to our buffer head
mov dx,es:BIOStail ; and the BIOS buffer tail.
mov cx,dx
call BIOSincbuff
cmp dx,es:BIOShead ; Make sure BIOS buffer not full
je udone
uloop:
cmp bx,cs:tail ; Check if we have any characters
je udone ; left to insert
mov ax,cs:[bx]
call incbuff
mov di,cx ; Make sure BIOS has room for at
mov cx,dx ; least two characters before
call BIOSincbuff ; inserting another
cmp dx,es:BIOShead
je udone
mov cs:head,bx ; If character was inserted, then
mov es:BIOStail,cx ; update the head and tail pointers
mov es:[di],ax
jmp uloop
udone:
ret
updateBIOS endp
;------ RepKey - repeat key only if the program is ready to accept more
repkey proc near
mov cs:repcount,1 ; Set fast repeat rate
mov dx,es:BIOStail
cmp dx,es:BIOShead ; Anti-skid braking check
jne rdone
mov bx,cs:lastchar ; Store repeat char in BX
xor ch,ch
mov cl,cs:repchars ; Set CX for # times to repeat char
reploop:
mov si,dx ; Repeat the character more than
call BIOSincbuff ; once in order to obtain speeds
mov es:[si],bx ; faster than 18.2 char / second
loop reploop
mov es:BIOStail,dx ; Update tail pointer
rdone:
ret
repkey endp
;------ IncBuff - Increment a FASTBUFF buffer pointer stored in BX
incbuff proc near
add bx,2
cmp bx,cs:endbuff
jne ok
mov bx,offset buffer
ok:
ret
incbuff endp
;------ BIOSincbuff - Same thing, but for BIOS buffer pointer in DX
BIOSincbuff proc near
add dx,2
cmp dx,BIOSendbuff
jne bok
mov dx,BIOSbuffer
bok:
ret
BIOSincbuff endp
;--------------------------------------------------------------------------
;Video Blanking / Restoring procedures
;--------------------------------------------------------------------------
;------BlankScreen - Turn off video display
blankscreen proc near
cli
push bx
push cx
push dx
push es
mov bx,BIOSdseg
mov es,bx
mov dx,03B8H
mov al,21H
out dx,al
mov cx,2B0CH
call setvideo
test word ptr es:BIOSequipflags,equipmask
jz jj1
mov al,21H
jmp jj2
jj1:
mov al,es:BIOScrtmodeset
and al,0F7H
mov es:BIOScrtmodeset,al
jj2:
mov dx,03D8H
out dx,al
test byte ptr es:BIOSpalette,palettemask
jz blankdone
mov al,es:BIOSpalette
and al,0F0H
mov dx,03D9H
out dx,al
blankdone:
and cs:switches,not scrmask ; Clear screen active flag
pop es
pop dx
pop cx
pop bx
sti
ret
blankscreen endp
;------ RestoreScreen - Turn video display back on
;
; ES contains BIOSdseg
restorescreen proc near
cli
push dx
push cx
mov dx,03B8H
mov al,29H
out dx,al
mov cx,0B0CH
call setvideo
test word ptr es:BIOSequipflags,equipmask
jz j1
mov al,29H
jmp j2
j1:
mov al,es:BIOScrtmodeset
or al,08H
mov es:BIOScrtmodeset,al
j2:
mov dx,03D8H
out dx,al
test byte ptr es:BIOSpalette,palettemask
jz restoredone
mov al,es:BIOSpalette
mov dx,03D9H
out dx,al
restoredone:
or cs:switches,scrmask ; Reset screen active flag
pop cx
pop dx
sti
ret
restorescreen endp
;------ SetVideo - set video according to contents of CX
;
; Destroys DX and AX registers also
setvideo proc near
mov dx,03B4H
mov al,0AH
out dx,al
inc dx
mov al,ch
out dx,al
mov al,0BH
out dx,al
inc dx
mov al,cl
out dx,al
ret
setvideo endp
;--------------------------------------------------------------------------
;Resident data area
;--------------------------------------------------------------------------
lastchar dw 0FFFFH ; Last character typed, undef at start
repcount db ? ; # ticks till next repeat
repchars db ? ; # chars to repeat per click
startdelay db ? ; Delay before repeating new char
scrcount dw ? ; Time left till screen blanked
screendelay dw ? ; Reset scrcount to this value
switches db 04H ; FASTBUFF off, screen active
;------ This portion must remain at the end, since the location of the
; end of the buffer indicates how large the resident portion is.
head dw buffer ; FASTBUFF buffer head and
tail dw buffer ; tail pointers
endbuff dw ? ; Contains address of last buffer spot
buffer dw ? ; New keyboard buffer.
;---------------------- Initialize vectors --------------------------------
;
; After successful initialization process release memory from
; here on down, terminate and stay resident.
;--------------------------------------------------------------------------
initialize:
assume cs:cseg,ds:cseg
mov bx,cs
mov ds,bx
call checkPSP ; Check command line parameters
cmp byte ptr hflag,0 ; hflag = 1 if we printed help
je checkinstall ; so don't install
jmp skipinstall
checkinstall:
mov ah,0FAH ; Check if FASTBUFF is already
int 10H ; installed
cmp ax,0FAH
jne installok
lea dx,error ; Print error message
mov ah,09H
int 21H
jmp skipinstall
installok:
lea dx,message ; Print installation message
mov ah,09H
int 21H
mov bh,defstart ; Set counters to default values
mov startdelay,bh ; or values entered via the command
mov bx,defscr ; line, whichever applies
mov screendelay,bx
mov scrcount,bx
cmp bx,0
je vidoff
or cs:switches,vidmask ; Turn on video blanking
vidoff:
mov bh,defspd
mov repchars,bh
xor ch,ch
mov cl,buffsize ; Determine buffer size in
shl cx,1 ; bytes and find endbuff address
add cx,offset buffer+2
mov endbuff,cx
push cx ; Store endbuff value for use as
; the resident program size later
mov bx,BIOSdseg
mov es,bx
mov bx,es:BIOStail ; Clear BIOS keyboard buffer
mov es:BIOShead,bx
mov al,09H ; Save old interrupt 09 vector
mov ah,35H ; and set new one.
int 21H
mov oldint9,bx
mov oldint9[2],es
mov dx,offset newint9
mov al,09H
mov ah,25H
int 21H
mov al,10H ; Save old interrupt 10 vector
mov ah,35H ; and set new one.
int 21H
mov oldint10,bx
mov oldint10[2],es
mov dx,offset newint10
mov al,10H
mov ah,25H
int 21H
mov al,1CH ; Save old interrupt 1C vector
mov ah,35H ; and set new one.
int 21H
mov oldint1C,bx
mov oldint1C[2],es
mov dx,offset newint1C
mov al,1CH
mov ah,25H
int 21H
or switches,fbmask ; Turn FASTBUFF on
pop dx ; Retrieve resident portion's size
; by popping the value saved earlier
; as CX, during endbuff calculation
int 27H ; Terminate & stay resident
skipinstall:
ret
;------ CheckPSP - Check command line parameters
;
; Note: this procedure may destroy any registers except DS
checkpsp proc near
mov dx,80H
mov si,dx
xor ah,ah
mov al,[si] ; Get length of paramter list
cmp al,0 ; Return if empty
je parmdone
add dx,ax
checkloop:
inc si
cmp byte ptr hflag,1
je parmdone
mov al,[si]
mov di,offset parmchars ; Check for '/'or'-' that starts a parm
mov cx,Lparmchars
cld
repne scasb
je gotparm
mov di,offset okchars ; Check for valid whitespace chars
mov cx,Lokchars
cld
repne scasb
je p1
call gethelp ; Invalid character found, output
jmp parmdone ; help screen and don't install
gotparm:
call foundparm
p1:
cmp si,dx
jb checkloop
parmdone:
ret
checkpsp endp
;------ FoundParm - Found a parameter, now decide what its for
foundparm proc near
inc si
mov al,[si]
mov di,offset parmtable
mov cx,Lparmtable
cld
repne scasb
jne h1
sub di,offset parmtable ; Calculate jump address
and di,0FFFEH
add di,offset jumptable
call word ptr [di]
jmp fdone
h1:
call gethelp ; Invalid parm, output help
fdone:
ret
foundparm endp
;------ SetBuff - Set new buffer size
setbuff proc near
call getnum
sub ax,14 ; We get 14 characters from BIOS buff
cmp al,11 ; Make sure we have room in our buffer
mov buffsize,al
jae sbok
call gethelp ; Get help if size invalid
sbok:
ret
setbuff endp
;------ SetFast - Set startup repeat rate to fast
setfast proc near
mov defspd,2
ret
setfast endp
;------ SetSlow - Set startup repeat rate to slow
setslow proc near
mov defspd,1
ret
setslow endp
;------ SetDelay - Set delay before a character starts repeating
setdelay proc near
call getnum
mov defstart,al
cmp ax,0
jne ddone
call gethelp
ddone:
ret
setdelay endp
;------ SetVid - Set amount of time before video is blanked
setvid proc near
push dx ; Multiply may use DX
call getnum
mov cx,1092
mul cx ; 1092 clicks per minute
mov defscr,ax
pop dx
ret
setvid endp
;------ GetHelp - Ouput help screen and set don't install flag (hflag)
gethelp proc near
push dx
mov byte ptr hflag,1 ; Set help flag
lea dx,help ; Print help screen
mov ah,09H
int 21H
pop dx
ret
gethelp endp
;------ GetNum - Calculate a number from the parameter list
;
; SI contains the current pointer into the PSP
; Returns the number in AX
getnum proc near
push bx
push cx
push dx ; Multiply may use DX
inc si
mov ax,0
mov cx,10
numloop:
xor bh,bh ; Accumulate number until
mov bl,[si] ; we hit a non-numeric character
cmp bl,'0'
jb numdone
cmp bl,'9'
ja numdone
mul cx
sub bl,'0'
add ax,bx
inc si
jmp numloop
numdone:
dec si ; Set SI to point to the last
pop dx ; character used
pop cx
pop bx
ret
getnum endp
;--------------------------------------------------------------------------
;Initialization data area
;--------------------------------------------------------------------------
okchars db ' ',',' ; Whitespace characters between parms
Lokchars equ $-okchars
parmchars db '/','-' ; Chars that indicate start of parm
Lparmchars equ $-parmchars
parmtable db 'b','B', 'f','F', 's','S', 'd','D', 'v','V'
Lparmtable equ $-parmtable
jumptable dw setbuff,setfast,setslow,setdelay,setvid
message db "FASTBUFF v2.0 keyboard enhancer installed.",cr,lf,"$"
hflag db 0
help db "┌──────────────────────────────────────────────────────────────────────────────┐"
db "│ ┌───────────────┐ │"
db "│ David Steiner │ FASTBUFF v2.0 │ November 1987 │"
db "│ └───────────────┘ │"
db "│ ╒══════════════════════════════════════════════════════╕ │"
db "│ │ Run-time Control Keys │ │"
db "│ ├──────────────────────────────────────────────────────┤ │"
db "│ │ Ctrl + Right Shift : Clear the keyboard buffer │ │"
db "│ │ [5] + Del key : Turns FASTBUFF off │ │"
db "│ │ [5] + Ins key : Turns FASTBUFF back on │ │"
db "│ │ [5] + Plus key : Selects fast repeat rate │ │"
db "│ │ [5] + Minus key : Selects slow repeat rate │ │"
db "│ │ │ │"
db "│ ╒════════╧══════════════════════════════════════════════════════╧════════╕ │"
db "│ │ Command Line Parameters : Min Max Default │ │"
db "│ ├────────────────────────────────────────────────────────────────────────┤ │"
db "│ │ /Bn : Sets the buffer size to n characters 25 269 100 │ │"
db "│ │ /Dn : Set start delay to n timer clicks 1 255 5 │ │"
db "│ │ /Vn : Set video blank delay to n minutes (0=OFF) 1 60 15 │ │"
db "│ │ /F : Startup repeat speed = fast - - ON │ │"
db "│ │ /S : Startup repeat speed = slow - - OFF │ │"
db "│ ╘════════════════════════════════════════════════════════════════════════╛ │"
db "└──────────────────────────────────────────────────────────────────────────────┘"
db "$"
error db "Error: FASTBUFF already installed.",cr,lf,"$"
;------ Default variables
defscr dw 16380 ; 15 minute delay before screen blanked
defstart db 5 ; Clicks before repeating new char
defspd db 2 ; Default characters per click
buffsize db 86 ; Buffer size (100, after subtracting
; addtional 14 chars in BIOS buff)
cseg ends
end start